﻿using System;
using System.Collections.Generic;
using System.Globalization;
using Logger;
using Vectors;

namespace Presenter
{
    public class Presenter:IPresenterCallbacks
    {

        public Vector3D ResultVector
        {
            get { return _domain.ResultVector; }
        }

        public double ResultScalar
        {
            get { return _domain.ResultScalar; }
        }

        public Vector3D FirstVector
        {
            get { return _domain.FirstVector; }
        }
        public Vector3D SecondVector
        {
            get { return _domain.SecondVector; }
        }

        private readonly Domain.Domain _domain;
        private readonly IView _view;
        private readonly ILogger _logger;

        public Presenter(IView view, ILogger logger)
        {
            _view = view;
            _logger = logger;
            _domain = new Domain.Domain();
        }

        private static Vector3D CreateVectorFromStringArray(IList<string> vectorArray)
        {
            var x = Double.Parse(vectorArray[0]);
            var y = Double.Parse(vectorArray[1]);
            var z = Double.Parse(vectorArray[2]);
            return new Vector3D(x, y, z);
       }

        public void SetVectorsFromViewIntoModel()
        {
            try
            {
                _view.HideResults();

                var firstVector = CreateVectorFromStringArray(_view.GetFirstVector());
                var secondVector = CreateVectorFromStringArray(_view.GetSecondVector());
                _domain.FirstVector = ReferenceEquals(firstVector, null) ? new Vector3D(0, 0, 0) : firstVector;
                _domain.SecondVector = ReferenceEquals(secondVector, null) ? new Vector3D(0, 0, 0) : secondVector;
            }
            catch (Exception exception)
            {
                _view.ShowError(exception.Message);
            }
        }

        public void ViewVectorResult()
        {
            var result = _domain.ResultVector;
            var strVector = new[] { result[0].ToString(CultureInfo.InvariantCulture), result[1].ToString(CultureInfo.InvariantCulture), result[2].ToString(CultureInfo.InvariantCulture) };
            _view.SetVectorResult(strVector);

        }

        public void ViewScalarResult()
        {
            var result = _domain.ResultScalar;
            _view.SetScalarResult(result.ToString(CultureInfo.InvariantCulture));
        }


        private string GetStringFromVector3D(Vector3D vector)
        {
            return vector.X.ToString(CultureInfo.InvariantCulture) + " " +
                   vector.Y.ToString(CultureInfo.InvariantCulture) + " " +
                   vector.Z.ToString(CultureInfo.InvariantCulture);
        }

        private void WriteRecordIntoLog(string operation,string result)
        {
            var record= operation + " : " + GetStringFromVector3D(_domain.FirstVector) + " , " +
                   GetStringFromVector3D(_domain.SecondVector) + " = " + result;
            _logger.WriteRecord(record);
            _view.AddLogRecord(record);
        }

        public void Add()
        {
            SetVectorsFromViewIntoModel();
            try
            {
                _domain.Add();
                ViewVectorResult();
                WriteRecordIntoLog("Add", GetStringFromVector3D(_domain.ResultVector));
            }
            catch (Exception exception)
            {
                _view.ShowError(exception.GetType() == typeof (NullReferenceException)
                                    ? "Неверные входные данные"
                                    : exception.Message);
            }
        }

        public void Sub()
        {
            SetVectorsFromViewIntoModel();
            try
            {
                _domain.Sub();
                ViewVectorResult();
                WriteRecordIntoLog("Sub", GetStringFromVector3D(_domain.ResultVector));
            }
            catch (Exception exception)
            {
                _view.ShowError(exception.GetType() == typeof(NullReferenceException)
                                    ? "Неверные входные данные"
                                    : exception.Message);
            }
        }

        public void Norm()
        {
            SetVectorsFromViewIntoModel();
            try
            {
                _domain.Norm();
                ViewScalarResult();
                WriteRecordIntoLog("Norm", _domain.ResultScalar.ToString(CultureInfo.InvariantCulture));
            }
            catch (Exception exception)
            {
                _view.ShowError(exception.GetType() == typeof(NullReferenceException)
                                    ? "Неверные входные данные"
                                    : exception.Message);
            }
        }

        public void Normalize()
        {
            SetVectorsFromViewIntoModel();
            try
            {
                _domain.Normalize();
                ViewVectorResult();
                WriteRecordIntoLog("Normalize", GetStringFromVector3D(_domain.ResultVector));
            }
            catch (Exception exception)
            {
                _view.ShowError(exception.GetType() == typeof(NullReferenceException)
                                    ? "Неверные входные данные"
                                    : exception.Message);
            }
        }

        public void LoadLog()
        {
            _view.AddLogRecord(_logger.ReadAllRecords());
        }

        public void ScalarProduct()
        {
            SetVectorsFromViewIntoModel();
            try
            {
                _domain.ScalarProduct();
                ViewScalarResult();
                WriteRecordIntoLog("ScalarProduct", GetStringFromVector3D(_domain.ResultVector));
            }
            catch (Exception exception)
            {
                _view.ShowError(exception.GetType() == typeof(NullReferenceException)
                                    ? "Неверные входные данные"
                                    : exception.Message);
            }
        }
      
        public void CrossProduct()
        {
            SetVectorsFromViewIntoModel();
            try
            {
                _domain.CrossProduct();
                ViewVectorResult();
                WriteRecordIntoLog("CrossProduct", GetStringFromVector3D(_domain.ResultVector));
            }
            catch (Exception exception)
            {
                _view.ShowError(exception.GetType() == typeof(NullReferenceException)
                                    ? "Неверные входные данные"
                                    : exception.Message);
            }
        }

    }
}
